4.3 ベクトル積和演算
MAUのベクトル積和演算の基本動作(第3.6.9.1節)の詳細について述べる。
一般化のため、第4.3節で述べた浮動小数点数フォーマットで仮数部長がmであるものを仮定する。半精
度、単精度、倍精度のそれぞれでm= 9, 23 , 52 となる。出力 1 要素に対する積和演算をab+cと表記し、積
の入力a, bはそれぞれ次で表される浮動小数点数であるとする:
code:txt
a= 2e(a)(−1)s(a)

1 +
code:txt
∑m
j=1
code:txt
2 −jAj

 (4.1)
code:txt
b= 2e(b)(−1)s(b)

1 +
code:txt
∑m
j=1
code:txt
2 −jBj

. (4.2)
ここで指数e(a), e(b)、符号s(a), s(b)∈{ 0 , 1 }、仮数部の各桁Aj, Bj∈{ 0 , 1 }の表記を用いた。仮数部に関す
る和の前の 1 はhidden bitに対応する。このとき積の厳密な値は
code:txt
ab= 2e(a)+e(b)(−1)s(a)+s(b)

1 +
code:txt
∑m
j=1
code:txt
2 −jAj+
code:txt
∑m
j=1
code:txt
2 −jBj+P

 (4.3)
P:=
∑
code:txt
1 ≤j,k≤m
code:txt
pj,k (4.4)
code:txt
pj,k:= 2−(j+k)AjBk (4.5)
となる。
半精度においてはPはこの表式どおりに計算される。単精度と倍精度においては、Pの代わりに、一部の
項pj,kを加算せず、代わりに補正項rを加えた値P′:=r+∑(j,k)∈Dpj,kを用いる。ここでDは精度ごとに
決まる部分積の加算範囲、rは加算されなかった桁Aj, Bks.t.(j, k)6∈Dによって決まる補正項である。
単精度においては
D:={(j, k)| 1 ≤j≤ 18 ∨ 1 ≤k≤ 18 } (4.6)
code:txt
r:=
code:txt
{ 0 if∑
(j,k)6∈Dpj,k= 0
2 −^38 otherwise (4.7)
であり、倍精度においては
code:txt
D:={(j, k)| 1 ≤j≤ 36 ∨ 1 ≤k≤ 36 } (4.8)
code:txt
r:=
code:txt
{ 0 if∑
(j,k)6∈Dpj,k= 0
2 −^74 otherwise (4.9)
である。すなわち、単精度では入力の仮数部の下位 23 −18 = 5ビット同士、倍精度では下位 52 −36 = 16
ビット同士の乗算を省略し、その結果がゼロになる場合を特別に検出してゼロとし、それ以外の場合は省略さ
れた仮数部の最上位にのみ 1 が立っていた場合と同じ結果とする。
いずれの精度でも積を計算したあとは同じで、以下を行ったのと同じ結果になる。
1.cを積との指数差分シフトして、仮数部長を無限として加算する
2.出力の浮動小数点数フォーマットの仮数部長に最近接偶数丸めで丸める。ここで繰り上がりにより指数
が変化しうることに注意
3.指数が出力の浮動小数点数フォーマットの無限や 0 の範囲に入っている場合、指数部を対応した値に
する
4.正規化を行って出力とする
オプションによっては精度拡張(基本動作より入力精度が低い)および精度縮減(基本動作より出力精度が高
い)が起きる。
精度拡張については単純に、基本動作の入力精度に変換してから基本動作が実行される。より高い精度への
変換は値が厳密一致するように行えるため、特に考えるべきことはない。
精度縮減については、最後の丸めは基本動作の出力精度に丸めてから精度縮減を行うのではなく、縮減後の
精度に直接丸められる。
単精度と倍精度における部分積の補正項への置き換えは、(hidden bit同士の積に由来する)最上位の桁から
出力の仮数部長分だけ下の桁よりもはるかに下の桁で起きるため、実用上ほとんどの場合に問題にならないと
考えられる。「はるかに下の桁」は具体的には、単精度では 38 −23 = 15ビット、倍精度では 74 −52 = 22
ビット下となる。厳密値との違いは以下のような大きなキャンセルが起きる場合に確認できる。
code:txt
imm f"1099511627776.0"$lr0/1000 # 2**40
imm f"1048577.0"$nowrite# 2**20+1
fvfma $aluf $aluf-$lr0 $ls0/1000 #exact: 2**21+1
d get $ls0n0c0b0m0p01 #printed: 0x4a000010
fvfmaの計算内容は(2^20 + 1)^2 − 240 である。厳密値は 221 + 1となり、これは単精度では0x4a000004で
ある。しかし、実際に$ls0に書き込まれるのは0x4a000010であり、厳密値との差が生じている。